package com.lieve.tx.twopc;

import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.jdbc.AtomikosDataSourceBean;
import lombok.extern.slf4j.Slf4j;

import javax.transaction.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Properties;

/**
 * @author sunyoboy
 * 2021/5/9
 */
@Slf4j
public class AtomikosJtaTest {

    private static AtomikosDataSourceBean createAtomikosDataSourceBean(String databaseName) {
        // 连接池基本属性
        Properties properties = new Properties();
        properties.setProperty("url", "jdbc:mysql://localhost:3306/" + databaseName);
        properties.setProperty("user", "root");
        properties.setProperty("password", "mysql");

        // 使用AtomikosDataSourceBean封装com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
        AtomikosDataSourceBean atomikosDataSourceBean = new AtomikosDataSourceBean();
        // 为每个AtomikosDataSourceBean设置名称
        atomikosDataSourceBean.setUniqueResourceName(databaseName);
        atomikosDataSourceBean.setXaDataSourceClassName("com.mysql.cj.jdbc.MysqlXADataSource");
        atomikosDataSourceBean.setXaProperties(properties);
        return atomikosDataSourceBean;
    }

    public static void main(String[] args) {
        AtomikosDataSourceBean ds1 = createAtomikosDataSourceBean("lieve_user");
        AtomikosDataSourceBean ds2 = createAtomikosDataSourceBean("lieve_account");
        Connection connection1 = null;
        Connection connection2 = null;
        PreparedStatement preparedStatement1 = null;
        PreparedStatement preparedStatement2 = null;
        UserTransaction userTransaction = new UserTransactionImp();
        try {
            // 开启事务
            userTransaction.begin();

            // 执行user库上的SQL
            connection1 = ds1.getConnection();
            preparedStatement1 = connection1.prepareStatement("INSERT INTO `user`(name) values (?) ");
            preparedStatement1.setString(1, "a");


            connection2 = ds2.getConnection();
            preparedStatement2 = connection2.prepareStatement("INSERT INTO account(name) values (?) ");
            preparedStatement2.setString(1, "b");


            preparedStatement1.executeUpdate();

            // 模拟异常
            int i = 1 / 0;

            preparedStatement2.executeUpdate();

            // 两阶段提交
            userTransaction.commit();
        } catch (Exception e) {
            e.printStackTrace();
            try {
                log.error("rollback");
                userTransaction.rollback();
            } catch (SystemException ex) {
                ex.printStackTrace();
            }
        } finally {
            try {
                preparedStatement1.close();
                preparedStatement2.close();
                connection1.close();
                connection2.close();
                ds1.close();
                ds2.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}
